#include "StdAfx.h"
#include "StreamIO.h"

using namespace System::IO;
using namespace System::Collections::Generic;

namespace SpikingNeuronLib
{
	// Look for a version line
	// Only consume characters if the line starts with 'V'
	double StreamIO::CheckVersion(StreamReader^ reader)
	{
		double result = 0.0;

		int data = reader->Peek();
		if (data >= 0)
		{
			if ((char)data == 'V')
			{
				reader->Read();		// consume it
				result = StreamIO::ScanStreamForType<double>(reader);
			}
		}

		return result;
	}

	generic <typename T>
	Nullable<T> StreamIO::ScanStream(StreamReader^ reader)
	{
		using namespace System::Text;

		List<wchar_t>^ item = gcnew List<wchar_t>(10);
		Nullable<T> result;

		// read past any whitespace
		int data;
		while ((data = reader->Peek()) >= 0)
		{
			char ch = (char) data;
			if (System::Char::IsWhiteSpace(ch))
			{
				reader->Read();		// consume it
			}
			else
			{
				break;
			}
		}

		// read until next whitespace
		// note that 33-44 is allowed and is equivalent to 33 -44
		while ((data = reader->Peek()) >= 0)
		{
			char ch = (char) data;
			if (System::Char::IsWhiteSpace(ch))
			{
				break;
			}
			else if (ch == '-' && item->Count > 0)	// treat '-' as end-of-item except when the item begins with '-'
			{
				break;
			}
			else
			{
				item->Add(ch);
				reader->Read();		// consume it
			}
		}

		// convert string
		if (item->Count > 0)
		{
			using namespace System::ComponentModel;
			Type^ ts = T::typeid;
			TypeConverter^ converter = TypeDescriptor::GetConverter(ts);

			T n;
			n = (T)converter->ConvertFromString(gcnew String(item->ToArray()));
			result = Nullable<T>(n);
		}

		return result;
	}

	generic <typename T>
	T StreamIO::ScanStreamForType(StreamReader^ reader)
	{
		Nullable<T> item = ScanStream<T>(reader);
		if (item.HasValue)
			return item.Value;
		else
			throw gcnew ArgumentException("Read error in ScanStream()");
	}
}
